﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExpressionLanguage
{
    public static class StringLibrary
    {
        private static bool String_Substring(List<ExpressionInterpreter.ExecutionStack.Variable> parameters, out ExpressionInterpreter.ExecutionStack.Variable result)
        {
            result = ExpressionInterpreter.ExecutionStack.Variable.MakeVoid();

            if (parameters.Count != 2 && parameters.Count != 3)
                return false;

            string value;
            double start, end;
            if (!parameters[0].AsString(out value))
                return false;
            if (!parameters[1].AsNumber(out start))
                return false;

            int istart;
            try
            {
                istart = (int)(start);
            }
            catch (InvalidCastException)
            {
                return false;
            }

            if (parameters.Count == 3)
            {
                if (!parameters[2].AsNumber(out end))
                    return false;
                int iend;
                try
                {
                    iend = (int)(end);
                }
                catch (InvalidCastException)
                {
                    return false;
                }
                result = new ExpressionInterpreter.ExecutionStack.Variable(value.Substring(istart, iend));
                return true;
            }
            else
            {
                result = new ExpressionInterpreter.ExecutionStack.Variable(value.Substring(istart));
                return true;
            }
        }

        private static bool String_Length(List<ExpressionInterpreter.ExecutionStack.Variable> parameters, out ExpressionInterpreter.ExecutionStack.Variable result)
        {
            result = ExpressionInterpreter.ExecutionStack.Variable.MakeVoid();

            string strvalue;

            if (parameters.Count != 1)
                return false;

            if (!parameters[0].AsString(out strvalue))
                return false;

            result = new ExpressionInterpreter.ExecutionStack.Variable(strvalue.Length);
            return true;
        }

        private static bool String_ToNumber(List<ExpressionInterpreter.ExecutionStack.Variable> parameters, out ExpressionInterpreter.ExecutionStack.Variable result)
        {
            result = ExpressionInterpreter.ExecutionStack.Variable.MakeVoid();

            string strvalue;

            if (parameters.Count != 1)
                return false;

            if (!parameters[0].AsString(out strvalue))
                return false;

            double number;

            try
            {
                number = Convert.ToDouble(strvalue);
            }
            catch (FormatException)
            {
                return false;
            }

            result = new ExpressionInterpreter.ExecutionStack.Variable(number);
            return true;
        }

        private static bool String_IndexOf(List<ExpressionInterpreter.ExecutionStack.Variable> parameters, out ExpressionInterpreter.ExecutionStack.Variable result)
        {
            result = ExpressionInterpreter.ExecutionStack.Variable.MakeVoid();

            if (parameters.Count != 3)
                return false;
            string sourceStr;
            string targetStr;
            double dindex;
            int iindex;
            if (!parameters[0].AsString(out sourceStr) ||
                !parameters[1].AsString(out targetStr) ||
                !parameters[2].AsNumber(out dindex))
                return false;
            try
            {
                iindex = (int)(dindex);
            }
            catch (InvalidCastException)
            {
                return false;
            }
            result = new ExpressionInterpreter.ExecutionStack.Variable(sourceStr.IndexOf(targetStr, iindex));
            return true;
        }


        public static void LoadLibrary( ExpressionInterpreter.GlobalFunction func, ExpressionInterpreter.ExecutionStack stack )
        {
            func.RegisterGlobalFunction("String.SubStr", StringLibrary.String_Substring);
            func.RegisterGlobalFunction("String.Length", StringLibrary.String_Length);
            func.RegisterGlobalFunction("String.ToNumber", StringLibrary.String_ToNumber);
            func.RegisterGlobalFunction("String.IndexOf", StringLibrary.String_IndexOf);
        }
    }
}
